package util

import (
	conf "OAM/conf"
	"context"
	"errors"
	"strconv"
	"sync"
	"time"

	"github.com/beego/beego/v2/client/cache"
)

const (
	CACHE_LOGIN_FAILED = "loginfailedcache"
	CACHE_DICT         = "dictitemcache"
	CACHE_COMMONS      = "_public_object"
)

var cacheMap map[string]MyCache

//继承beego cache,简化缓存操作
type MyCache struct {
	cache.Cache
	//name     string
	interval int
	*sync.RWMutex
}

func init() {
	cacheMap = make(map[string]MyCache)
	//先定义要用到的缓存配置, 具体缓存对象延迟初始化
	loginFailedCache := MyCache{interval: 60, RWMutex: &sync.RWMutex{}}
	cacheMap[CACHE_LOGIN_FAILED] = loginFailedCache

	dictCache := MyCache{interval: 300, RWMutex: &sync.RWMutex{}}
	cacheMap[CACHE_DICT] = dictCache

	commons_cache := MyCache{interval: 300, RWMutex: &sync.RWMutex{}}
	cacheMap[CACHE_COMMONS] = commons_cache
}

func (m MyCache) Get(key string) (interface{}, error) {
	return m.Cache.Get(context.TODO(), key)
}

// 从缓存中取string值,如果不存在返回空字符串,请确保值一定是string类型
func (m MyCache) GetString(key string) string {
	val, err := m.Cache.Get(context.TODO(), key)
	if err != nil {
		return ""
	}
	return val.(string)
}

// 从缓存中取int类型值,如果不存在返回0,int
func (m MyCache) GetInt(key string) int {
	val, err := m.Cache.Get(context.TODO(), key)
	if err != nil {
		return 0
	}
	return val.(int)
}

// 缓存对象
func (m MyCache) Put(key string, value interface{}, timeout time.Duration) {
	m.Cache.Put(context.TODO(), key, value, timeout)
}

func (m MyCache) Incr(key string) error {
	return m.Cache.Incr(context.TODO(), key)
}

func (m MyCache) Delete(key string) {
	m.Cache.Delete(context.TODO(), key)
}

// 创建一个缓存. 参数interval表示清理缓存间隔时间
func CreateCache(name string, interval int) MyCache {
	var mycache MyCache
	c, err := cache.NewCache(conf.GlobalCfg.CACHE_TYPE, `{"interval":`+strconv.Itoa(interval)+`}`)
	if err != nil {
		panic(errors.New("缓存初始失败"))
	}
	mycache = MyCache{Cache: c}
	return mycache
}

func GetCache(name string) MyCache {
	mc, ok := cacheMap[name]
	if ok {
		if mc.Cache == nil {
			mc.Lock()
			if mc.Cache == nil {
				c, err := cache.NewCache(conf.GlobalCfg.CACHE_TYPE, `{"interval":`+strconv.Itoa(mc.interval)+`}`)
				if err != nil {
					mc.Unlock()
					panic(errors.New("缓存初始失败"))
				}
				mc.Cache = c
				cacheMap[name] = mc
			}
			mc.Unlock()
		}
		return mc
	} else {
		panic("试图获取未定义的缓存")
	}
}

func GetPublicCache() MyCache {
	return GetCache(CACHE_COMMONS)
}
